package modelPackage;

import java.awt.Point;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Map3D {
	
	private ArrayList<Map> maps;
	private Map sideMap;
	
	private int height;
	private int width;
	private int depth;
	
	static private String location = "map/";
	static private String extension = ".txt";
	
	static private int TILE_SIZE = 50;
	
	public Map3D(String filename) {
		maps = new ArrayList<Map>();
		sideMap = null;
		height = 0;
		width = 0;
		depth = 0;
		
		this.loadAllMaps(filename);
	}
	
	/**
	 * A function to load all of the maps from the maplist file.
	 * @param filename
	 */
	public void loadAllMaps(String filename) {
		
		filename = location + filename + extension;
		
		//Create a reader to read text in from list of files.
		BufferedReader file = null;
		try {
			file = new BufferedReader(new FileReader(filename));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
		//Read in each line from the text file.
		String line = null;		
		
		while (true) {
			try {
				line = file.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			//If a null line is read in, stop reading lines.
			if (line == null) {
				try {
					file.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				break;
			}
			
			//If the line is commented out, ignore it.
			//Comments can be signified by // -- # * ;
			if (line.startsWith("//") || line.startsWith("--") || line.startsWith("#") || line.startsWith("*") || line.startsWith(";")) {
				//Do nothing.
			}
			else if (line.startsWith("num:")) {
				this.depth = Integer.parseInt(line.substring(4));
			}
			else if (line.startsWith("f:")) {
				this.sideMap = new Map(line.substring(2));
			}
			else {
				//Then load the little map, and add it to the array of little maps
				Map m = new Map(line);
				this.maps.add(m);
			}
		}
		depth = this.maps.size();
		height = sideMap.getHeight();
		width = sideMap.getWidth();
	} 
	
	
	// These are used to check collisions and to draw stuff.
	
	public boolean solidTileLeft(Point3D p) {
		if (p.z < TILE_SIZE || p.z > this.getDepth()*TILE_SIZE) {
			return false;
		}
		else {
			if (this.maps.get(((int) p.z / TILE_SIZE) - 1).getSolidTile(new Point((int) p.x, (int) p.y)) != null) {
				return true;
			}
			else {
				return false;
			}
		}		
	}
	public boolean solidTileRight(Point3D p) {
		if (p.z < 0 || p.z >= (this.getDepth()*TILE_SIZE) - TILE_SIZE) {
			return false;
		}
		else {
			if (this.maps.get(((int) p.z / TILE_SIZE) + 1).getSolidTile(new Point((int) p.x, (int) p.y)) != null) {
				return true;
			}
			else {
				return false;
			}
		}	
	}
	public boolean solidTileAbove(Point3D p) {
		if (p.y < 0 || p.y > this.getHeight()*TILE_SIZE) {
			return false;
		}
		else {
			if (this.maps.get((int) p.z / TILE_SIZE).solidTileAbove(this.maps.get((int) p.z /TILE_SIZE).getTile(new Point((int) p.x, (int) p.y))) == true) {
				return true;
			}
			else {
				return false;
			}
		}
	}
	public boolean solidTileBelow(Point3D p) {
		if (p.y < 0 || p.y > this.getHeight()*TILE_SIZE) {
			return false;
		}
		else {
			if (this.maps.get((int) p.z / TILE_SIZE).solidTileBelow(this.maps.get((int) p.z /TILE_SIZE).getTile(new Point((int) p.x, (int) p.y))) == true) {
				return true;
			}
			else {
				return false;
			}
		}
	}
	public boolean solidTileFront(Point3D p) {
		if (p.x < 0 || p.x > this.getWidth()*TILE_SIZE) {
			return false;
		}
		else {
			if (this.maps.get((int) p.z / TILE_SIZE).solidTileRight(this.maps.get((int) p.z /TILE_SIZE).getTile(new Point((int) p.x, (int) p.y))) == true) {
				return true;
			}
			else {
				return false;
			}
		}
	}
	public boolean solidTileBehind(Point3D p) {
		if (p.x < 0 || p.x > this.getWidth()*TILE_SIZE) {
			return false;
		}
		else {
			if (this.maps.get((int) p.z / TILE_SIZE).solidTileLeft(this.maps.get((int) p.z /TILE_SIZE).getTile(new Point((int) p.x, (int) p.y))) == true) {
				return true;
			}
			else {
				return false;
			}
		}
	}

	
	
	public String getBuilding() {
		return this.sideMap.getBuilding();
	}
	
	public int getFloor() {
		return this.sideMap.getFloor();
	}
	
	public Map get2DMap() {
		return sideMap;
	}
	
	public ArrayList<Map> getMaps() {
		return this.maps;
	}
	
	public int getHeight() {
		return this.height;
	}
	
	public int getWidth() {
		return this.width;
	}
	
	public int getDepth() {
		return this.depth;
	}
	
}
